{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import networkx as nx\n",
    "\n",
    "from example_stats import d_connected_triplet_motif_density"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 9 1 ... 0 0 0]\n",
      " [1 0 1 ... 0 0 0]\n",
      " [2 3 1 ... 0 0 0]\n",
      " ...\n",
      " [0 0 0 ... 0 0 0]\n",
      " [0 0 0 ... 0 0 0]\n",
      " [0 1 0 ... 0 0 0]]\n"
     ]
    }
   ],
   "source": [
    "G = nx.DiGraph(nx.scale_free_graph(100))\n",
    "adj = nx.convert_matrix.to_scipy_sparse_matrix(A)\n",
    "print(adj.toarray())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Utility functions for manipulating motif counts\n",
    "def directed_triplet_motif_index(G):\n",
    "    \"\"\"Return the directed motif index of three-node graph G (G is a nx graph type)\n",
    "    \n",
    "    The motif index is then computed as follows:\n",
    "    Each possible (undirected) edge on the nodes of G is sorted in lexicographic order.\n",
    "    For each pair of vertices, two bits encode, in order, the presence of the edge from\n",
    "    lower index to higher index and the edge from higher index to lower index. These bits\n",
    "    are reversed and concatenated to form a single integer\n",
    "    \n",
    "    Example: G has three nodes, labeled i,j,k in sorted order. It has edge ij, ik, ki, and kj.\n",
    "    The lex order for the pairs is ij, ik, jk. Pair ij has edge ij (low-high) but not ji (high-low),\n",
    "    so the least significant bit is 1 and the second-least significant bit is 0. For pair ik, we have both\n",
    "    directed edges so those bits are 11. Lastly, pair jk has only the high-low edge, so the higher-order\n",
    "    bit is 1 while the lower bit is 0. Putting these bits together from right to left we get 101101,\n",
    "    which is 45 in decimal.\n",
    "    \n",
    "    !!! Note that the order of vertice s in G has nothing to do with numerical order!\n",
    "        See networkx documentation about classes OrderedGraph and OrderedDiGraph.\n",
    "    \n",
    "    Returns an integer between 0 and 63 (inclusive)\n",
    "    \"\"\"\n",
    "    bit_selector = np.array([[0,1,4], [2,0,16], [8, 32, 0]])\n",
    "    return np.sum(np.multiply(bit_selector, nx.to_numpy_matrix(G).astype(int)))\n",
    "\n",
    "def directed_triplet_motif_index_from_matrix(M):\n",
    "    \"\"\"Same as directed_triplet_motif_index but accepts a numpy matrix as its argument\"\"\"\n",
    "    bit_selector = np.array([[0,1,4], [2,0,16], [8, 32, 0]])\n",
    "    return np.sum(np.multiply(bit_selector, M))\n",
    "\n",
    "\n",
    "def binary_digits(n, d):  # numpy-optimized\n",
    "    \"\"\"Returns an n x d array of the binary digits of each entry of array n\n",
    "    Parameters:\n",
    "        n : array_like\n",
    "            Integer values to be represented as binary digits\n",
    "        d : the number of digits; zero padding and/or truncation if necessary\n",
    "    Returns:\n",
    "        digits : an n x d binary array; each row is the digits of the corresponding entry of n. Least significant bit has index 0.\n",
    "    \"\"\"\n",
    "    return ((n[:, None] & (1 << np.arange(d))) > 0).astype(int)\n",
    "\n",
    "def index_to_directed_triplet_motif_matrix(n):\n",
    "    \"\"\"Return the adjacency matrix corresponding to motif with index n, as defined by the function\n",
    "    directed_triplet_motif_index\"\"\"\n",
    "    digs = binary_digits(np.array([n]),6)\n",
    "    A = np.zeros((3,3), dtype=int)\n",
    "    A[tuple([[0,1,0,2,1,2],[1,0,2,0,2,1]])] = digs\n",
    "    return A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 [[0 0 0]\n",
      " [0 0 0]\n",
      " [0 0 0]]\n",
      "1 [[0 1 0]\n",
      " [0 0 0]\n",
      " [0 0 0]]\n",
      "2 [[0 0 0]\n",
      " [1 0 0]\n",
      " [0 0 0]]\n",
      "3 [[0 1 0]\n",
      " [1 0 0]\n",
      " [0 0 0]]\n",
      "4 [[0 0 1]\n",
      " [0 0 0]\n",
      " [0 0 0]]\n",
      "5 [[0 1 1]\n",
      " [0 0 0]\n",
      " [0 0 0]]\n",
      "6 [[0 0 1]\n",
      " [1 0 0]\n",
      " [0 0 0]]\n",
      "7 [[0 1 1]\n",
      " [1 0 0]\n",
      " [0 0 0]]\n",
      "8 [[0 0 0]\n",
      " [0 0 0]\n",
      " [1 0 0]]\n",
      "9 [[0 1 0]\n",
      " [0 0 0]\n",
      " [1 0 0]]\n",
      "10 [[0 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n",
      "11 [[0 1 0]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n",
      "12 [[0 0 1]\n",
      " [0 0 0]\n",
      " [1 0 0]]\n",
      "13 [[0 1 1]\n",
      " [0 0 0]\n",
      " [1 0 0]]\n",
      "14 [[0 0 1]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n",
      "15 [[0 1 1]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n",
      "16 [[0 0 0]\n",
      " [0 0 1]\n",
      " [0 0 0]]\n",
      "17 [[0 1 0]\n",
      " [0 0 1]\n",
      " [0 0 0]]\n",
      "18 [[0 0 0]\n",
      " [1 0 1]\n",
      " [0 0 0]]\n",
      "19 [[0 1 0]\n",
      " [1 0 1]\n",
      " [0 0 0]]\n",
      "20 [[0 0 1]\n",
      " [0 0 1]\n",
      " [0 0 0]]\n",
      "21 [[0 1 1]\n",
      " [0 0 1]\n",
      " [0 0 0]]\n",
      "22 [[0 0 1]\n",
      " [1 0 1]\n",
      " [0 0 0]]\n",
      "23 [[0 1 1]\n",
      " [1 0 1]\n",
      " [0 0 0]]\n",
      "24 [[0 0 0]\n",
      " [0 0 1]\n",
      " [1 0 0]]\n",
      "25 [[0 1 0]\n",
      " [0 0 1]\n",
      " [1 0 0]]\n",
      "26 [[0 0 0]\n",
      " [1 0 1]\n",
      " [1 0 0]]\n",
      "27 [[0 1 0]\n",
      " [1 0 1]\n",
      " [1 0 0]]\n",
      "28 [[0 0 1]\n",
      " [0 0 1]\n",
      " [1 0 0]]\n",
      "29 [[0 1 1]\n",
      " [0 0 1]\n",
      " [1 0 0]]\n",
      "30 [[0 0 1]\n",
      " [1 0 1]\n",
      " [1 0 0]]\n",
      "31 [[0 1 1]\n",
      " [1 0 1]\n",
      " [1 0 0]]\n",
      "32 [[0 0 0]\n",
      " [0 0 0]\n",
      " [0 1 0]]\n",
      "33 [[0 1 0]\n",
      " [0 0 0]\n",
      " [0 1 0]]\n",
      "34 [[0 0 0]\n",
      " [1 0 0]\n",
      " [0 1 0]]\n",
      "35 [[0 1 0]\n",
      " [1 0 0]\n",
      " [0 1 0]]\n",
      "36 [[0 0 1]\n",
      " [0 0 0]\n",
      " [0 1 0]]\n",
      "37 [[0 1 1]\n",
      " [0 0 0]\n",
      " [0 1 0]]\n",
      "38 [[0 0 1]\n",
      " [1 0 0]\n",
      " [0 1 0]]\n",
      "39 [[0 1 1]\n",
      " [1 0 0]\n",
      " [0 1 0]]\n",
      "40 [[0 0 0]\n",
      " [0 0 0]\n",
      " [1 1 0]]\n",
      "41 [[0 1 0]\n",
      " [0 0 0]\n",
      " [1 1 0]]\n",
      "42 [[0 0 0]\n",
      " [1 0 0]\n",
      " [1 1 0]]\n",
      "43 [[0 1 0]\n",
      " [1 0 0]\n",
      " [1 1 0]]\n",
      "44 [[0 0 1]\n",
      " [0 0 0]\n",
      " [1 1 0]]\n",
      "45 [[0 1 1]\n",
      " [0 0 0]\n",
      " [1 1 0]]\n",
      "46 [[0 0 1]\n",
      " [1 0 0]\n",
      " [1 1 0]]\n",
      "47 [[0 1 1]\n",
      " [1 0 0]\n",
      " [1 1 0]]\n",
      "48 [[0 0 0]\n",
      " [0 0 1]\n",
      " [0 1 0]]\n",
      "49 [[0 1 0]\n",
      " [0 0 1]\n",
      " [0 1 0]]\n",
      "50 [[0 0 0]\n",
      " [1 0 1]\n",
      " [0 1 0]]\n",
      "51 [[0 1 0]\n",
      " [1 0 1]\n",
      " [0 1 0]]\n",
      "52 [[0 0 1]\n",
      " [0 0 1]\n",
      " [0 1 0]]\n",
      "53 [[0 1 1]\n",
      " [0 0 1]\n",
      " [0 1 0]]\n",
      "54 [[0 0 1]\n",
      " [1 0 1]\n",
      " [0 1 0]]\n",
      "55 [[0 1 1]\n",
      " [1 0 1]\n",
      " [0 1 0]]\n",
      "56 [[0 0 0]\n",
      " [0 0 1]\n",
      " [1 1 0]]\n",
      "57 [[0 1 0]\n",
      " [0 0 1]\n",
      " [1 1 0]]\n",
      "58 [[0 0 0]\n",
      " [1 0 1]\n",
      " [1 1 0]]\n",
      "59 [[0 1 0]\n",
      " [1 0 1]\n",
      " [1 1 0]]\n",
      "60 [[0 0 1]\n",
      " [0 0 1]\n",
      " [1 1 0]]\n",
      "61 [[0 1 1]\n",
      " [0 0 1]\n",
      " [1 1 0]]\n",
      "62 [[0 0 1]\n",
      " [1 0 1]\n",
      " [1 1 0]]\n",
      "63 [[0 1 1]\n",
      " [1 0 1]\n",
      " [1 1 0]]\n"
     ]
    }
   ],
   "source": [
    "for k in range(64):\n",
    "    print(k, index_to_directed_triplet_motif_matrix(k))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.arange(400).reshape((20,20))\n",
    "partition = {\"A\": (0,4), \"B\": (4,10), \"C\": (10,17), \"D\": (17,20)}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A [0, 1, 2, 3]\n",
      "B [4, 5, 6, 7, 8, 9]\n",
      "C [10, 11, 12, 13, 14, 15, 16]\n",
      "D [17, 18, 19]\n"
     ]
    }
   ],
   "source": [
    "for c, r in partition.items():\n",
    "    print(c, list(range(*r)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4,  5,  6,  7,  8,  9],\n",
       "       [24, 25, 26, 27, 28, 29],\n",
       "       [44, 45, 46, 47, 48, 49],\n",
       "       [64, 65, 66, 67, 68, 69]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[partition[\"A\"][0]:partition[\"A\"][1], partition[\"B\"][0]:partition[\"B\"][1]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4,  5,  6,  7,  8,  9],\n",
       "       [24, 25, 26, 27, 28, 29],\n",
       "       [44, 45, 46, 47, 48, 49],\n",
       "       [64, 65, 66, 67, 68, 69]])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b[np.ix_(partition[\"A\"], partition[\"B\"])]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20.9 µs ± 1.66 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit sub_matrix = b[partition[\"A\"],:][:,partition[\"B\"]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "34.5 µs ± 3.35 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit sub_matrix = b[np.ix_(partition[\"A\"], partition[\"B\"])]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "646 ns ± 14.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit sub_matrix = b[partition[\"A\"][0]:partition[\"A\"][1], partition[\"B\"][0]:partition[\"B\"][1]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (<ipython-input-63-c9b768c89bb6>, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  File \u001b[0;32m\"<ipython-input-63-c9b768c89bb6>\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m    b[[1:4, 5:7], [1:4, 5:7]]\u001b[0m\n\u001b[0m        ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "b[[1:4, 5:7], [1:4, 5:7]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  0,   1,   2,   3,  10,  11,  12,  13,  14,  15,  16],\n",
       "       [ 20,  21,  22,  23,  30,  31,  32,  33,  34,  35,  36],\n",
       "       [ 40,  41,  42,  43,  50,  51,  52,  53,  54,  55,  56],\n",
       "       [ 60,  61,  62,  63,  70,  71,  72,  73,  74,  75,  76],\n",
       "       [200, 201, 202, 203, 210, 211, 212, 213, 214, 215, 216],\n",
       "       [220, 221, 222, 223, 230, 231, 232, 233, 234, 235, 236],\n",
       "       [240, 241, 242, 243, 250, 251, 252, 253, 254, 255, 256],\n",
       "       [260, 261, 262, 263, 270, 271, 272, 273, 274, 275, 276],\n",
       "       [280, 281, 282, 283, 290, 291, 292, 293, 294, 295, 296],\n",
       "       [300, 301, 302, 303, 310, 311, 312, 313, 314, 315, 316],\n",
       "       [320, 321, 322, 323, 330, 331, 332, 333, 334, 335, 336]])"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.vstack([np.hstack([b[0:4, 0:4], b[0:4, 10:17]]), np.hstack([b[10:17, 0:4], b[10:17, 10:17]])])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 1],\n",
       "       [1, 0, 0],\n",
       "       [0, 0, 0]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = index_to_directed_triplet_motif_matrix(7)\n",
    "m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "yep\n"
     ]
    }
   ],
   "source": [
    "if m[1,0] | m[0,1]:\n",
    "    print(\"yep\")\n",
    "else:\n",
    "    print(\"nop\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m[0,1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(m[i,j] | m[j,i] for i in range(3) for j in range(i,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 1 0\n"
     ]
    }
   ],
   "source": [
    "c12 = m[0,1] | m[1,0]\n",
    "c13 = m[0,2] | m[2,0]\n",
    "c23 = m[1,2] | m[2,1]\n",
    "print(c12, c13, c23)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true,
     "source_hidden": true
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 [[0 0 0]\n",
      " [0 0 0]\n",
      " [0 0 0]]\n",
      "none of them!\n",
      "1 [[0 1 0]\n",
      " [0 0 0]\n",
      " [0 0 0]]\n",
      "Only c12\n",
      "2 [[0 0 0]\n",
      " [1 0 0]\n",
      " [0 0 0]]\n",
      "Only c12\n",
      "3 [[0 1 0]\n",
      " [1 0 0]\n",
      " [0 0 0]]\n",
      "Only c12\n",
      "4 [[0 0 1]\n",
      " [0 0 0]\n",
      " [0 0 0]]\n",
      "only c13\n",
      "5 [[0 1 1]\n",
      " [0 0 0]\n",
      " [0 0 0]]\n",
      "c12 and c13 but not c23\n",
      "6 [[0 0 1]\n",
      " [1 0 0]\n",
      " [0 0 0]]\n",
      "c12 and c13 but not c23\n",
      "7 [[0 1 1]\n",
      " [1 0 0]\n",
      " [0 0 0]]\n",
      "c12 and c13 but not c23\n",
      "8 [[0 0 0]\n",
      " [0 0 0]\n",
      " [1 0 0]]\n",
      "only c13\n",
      "9 [[0 1 0]\n",
      " [0 0 0]\n",
      " [1 0 0]]\n",
      "c12 and c13 but not c23\n",
      "10 [[0 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n",
      "c12 and c13 but not c23\n",
      "11 [[0 1 0]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n",
      "c12 and c13 but not c23\n",
      "12 [[0 0 1]\n",
      " [0 0 0]\n",
      " [1 0 0]]\n",
      "only c13\n",
      "13 [[0 1 1]\n",
      " [0 0 0]\n",
      " [1 0 0]]\n",
      "c12 and c13 but not c23\n",
      "14 [[0 0 1]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n",
      "c12 and c13 but not c23\n",
      "15 [[0 1 1]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n",
      "c12 and c13 but not c23\n",
      "16 [[0 0 0]\n",
      " [0 0 1]\n",
      " [0 0 0]]\n",
      "only c23\n",
      "17 [[0 1 0]\n",
      " [0 0 1]\n",
      " [0 0 0]]\n",
      "c12 and c23, but not c13\n",
      "18 [[0 0 0]\n",
      " [1 0 1]\n",
      " [0 0 0]]\n",
      "c12 and c23, but not c13\n",
      "19 [[0 1 0]\n",
      " [1 0 1]\n",
      " [0 0 0]]\n",
      "c12 and c23, but not c13\n",
      "20 [[0 0 1]\n",
      " [0 0 1]\n",
      " [0 0 0]]\n",
      "missing c12\n",
      "21 [[0 1 1]\n",
      " [0 0 1]\n",
      " [0 0 0]]\n",
      "got 'em all\n",
      "22 [[0 0 1]\n",
      " [1 0 1]\n",
      " [0 0 0]]\n",
      "got 'em all\n",
      "23 [[0 1 1]\n",
      " [1 0 1]\n",
      " [0 0 0]]\n",
      "got 'em all\n",
      "24 [[0 0 0]\n",
      " [0 0 1]\n",
      " [1 0 0]]\n",
      "missing c12\n",
      "25 [[0 1 0]\n",
      " [0 0 1]\n",
      " [1 0 0]]\n",
      "got 'em all\n",
      "26 [[0 0 0]\n",
      " [1 0 1]\n",
      " [1 0 0]]\n",
      "got 'em all\n",
      "27 [[0 1 0]\n",
      " [1 0 1]\n",
      " [1 0 0]]\n",
      "got 'em all\n",
      "28 [[0 0 1]\n",
      " [0 0 1]\n",
      " [1 0 0]]\n",
      "missing c12\n",
      "29 [[0 1 1]\n",
      " [0 0 1]\n",
      " [1 0 0]]\n",
      "got 'em all\n",
      "30 [[0 0 1]\n",
      " [1 0 1]\n",
      " [1 0 0]]\n",
      "got 'em all\n",
      "31 [[0 1 1]\n",
      " [1 0 1]\n",
      " [1 0 0]]\n",
      "got 'em all\n",
      "32 [[0 0 0]\n",
      " [0 0 0]\n",
      " [0 1 0]]\n",
      "only c23\n",
      "33 [[0 1 0]\n",
      " [0 0 0]\n",
      " [0 1 0]]\n",
      "c12 and c23, but not c13\n",
      "34 [[0 0 0]\n",
      " [1 0 0]\n",
      " [0 1 0]]\n",
      "c12 and c23, but not c13\n",
      "35 [[0 1 0]\n",
      " [1 0 0]\n",
      " [0 1 0]]\n",
      "c12 and c23, but not c13\n",
      "36 [[0 0 1]\n",
      " [0 0 0]\n",
      " [0 1 0]]\n",
      "missing c12\n",
      "37 [[0 1 1]\n",
      " [0 0 0]\n",
      " [0 1 0]]\n",
      "got 'em all\n",
      "38 [[0 0 1]\n",
      " [1 0 0]\n",
      " [0 1 0]]\n",
      "got 'em all\n",
      "39 [[0 1 1]\n",
      " [1 0 0]\n",
      " [0 1 0]]\n",
      "got 'em all\n",
      "40 [[0 0 0]\n",
      " [0 0 0]\n",
      " [1 1 0]]\n",
      "missing c12\n",
      "41 [[0 1 0]\n",
      " [0 0 0]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "42 [[0 0 0]\n",
      " [1 0 0]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "43 [[0 1 0]\n",
      " [1 0 0]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "44 [[0 0 1]\n",
      " [0 0 0]\n",
      " [1 1 0]]\n",
      "missing c12\n",
      "45 [[0 1 1]\n",
      " [0 0 0]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "46 [[0 0 1]\n",
      " [1 0 0]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "47 [[0 1 1]\n",
      " [1 0 0]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "48 [[0 0 0]\n",
      " [0 0 1]\n",
      " [0 1 0]]\n",
      "only c23\n",
      "49 [[0 1 0]\n",
      " [0 0 1]\n",
      " [0 1 0]]\n",
      "c12 and c23, but not c13\n",
      "50 [[0 0 0]\n",
      " [1 0 1]\n",
      " [0 1 0]]\n",
      "c12 and c23, but not c13\n",
      "51 [[0 1 0]\n",
      " [1 0 1]\n",
      " [0 1 0]]\n",
      "c12 and c23, but not c13\n",
      "52 [[0 0 1]\n",
      " [0 0 1]\n",
      " [0 1 0]]\n",
      "missing c12\n",
      "53 [[0 1 1]\n",
      " [0 0 1]\n",
      " [0 1 0]]\n",
      "got 'em all\n",
      "54 [[0 0 1]\n",
      " [1 0 1]\n",
      " [0 1 0]]\n",
      "got 'em all\n",
      "55 [[0 1 1]\n",
      " [1 0 1]\n",
      " [0 1 0]]\n",
      "got 'em all\n",
      "56 [[0 0 0]\n",
      " [0 0 1]\n",
      " [1 1 0]]\n",
      "missing c12\n",
      "57 [[0 1 0]\n",
      " [0 0 1]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "58 [[0 0 0]\n",
      " [1 0 1]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "59 [[0 1 0]\n",
      " [1 0 1]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "60 [[0 0 1]\n",
      " [0 0 1]\n",
      " [1 1 0]]\n",
      "missing c12\n",
      "61 [[0 1 1]\n",
      " [0 0 1]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "62 [[0 0 1]\n",
      " [1 0 1]\n",
      " [1 1 0]]\n",
      "got 'em all\n",
      "63 [[0 1 1]\n",
      " [1 0 1]\n",
      " [1 1 0]]\n",
      "got 'em all\n"
     ]
    }
   ],
   "source": [
    "for k in range(64):\n",
    "    m = index_to_directed_triplet_motif_matrix(k)\n",
    "    print(k, m)\n",
    "    c12 = m[0,1] + m[1,0]\n",
    "    c13 = m[0,2] + m[2,0]\n",
    "    c23 = m[1,2] + m[2,1]\n",
    "    if not c12 and not c13 and not c23:\n",
    "        print(\"none of them!\")\n",
    "    elif c12 and not c13 and not c23:\n",
    "        print(\"Only c12\")\n",
    "    elif not c12 and c13 and not c23:\n",
    "        print(\"only c13\")\n",
    "    elif not c12 and not c13 and c23:\n",
    "        print(\"only c23\")\n",
    "    elif c12 and c13 and not c23:\n",
    "        print(\"c12 and c13 but not c23\")\n",
    "    elif c12 and not c13 and c23:\n",
    "        print(\"c12 and c23, but not c13\")\n",
    "    elif not c12 and c13 and c23:\n",
    "        print(\"missing c12\")\n",
    "    else:\n",
    "        print(\"got 'em all\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0;31mInit signature:\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m/\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
       "\u001b[0;31mDocstring:\u001b[0m     \n",
       "range(stop) -> range object\n",
       "range(start, stop[, step]) -> range object\n",
       "\n",
       "Return an object that produces a sequence of integers from start (inclusive)\n",
       "to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.\n",
       "start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.\n",
       "These are exactly the valid indices for a list of 4 elements.\n",
       "When step is given, it specifies the increment (or decrement).\n",
       "\u001b[0;31mType:\u001b[0m           type\n",
       "\u001b[0;31mSubclasses:\u001b[0m     \n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "?range"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(reversed(range(10)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "577 ns ± 7.81 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit m[0,1] & m[1,0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "593 ns ± 10.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit m[0,1] * m[1,0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4.5 µs ± 133 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "c1 = \"A\"\n",
    "c2 = \"B\"\n",
    "%timeit max(1, (c1 == c2) + m[0,1] + m[1,0] - 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4.1 µs ± 132 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit 1 + ((c1 == c2) & m[0,1] & m[1,0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4.11 µs ± 114 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit ((c1 == c2) & m[0,1] & m[1,0]) + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
